package com.app.utils;

import com.app.pojo.Share;
import com.app.config.Settings;

import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Objects;

public class FileUtils {
    final static String usersDir= Settings.usersDir;
    final static String rootsDir= Settings.rootsDir;



    /**
     * 移动/重命名、复制
     * @param source 原文件 带id
     * @param target 新文件地址，带id
     * @return 成功与否
     */
    public static boolean renameFile(String source,String target,boolean copy){
        try {
            return copy?
                    Files.copy(Paths.get(rootsDir,source),Paths.get(rootsDir,target)).toFile().exists()
                    :getRootFile(source).renameTo(getRootFile(target));
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 建立一个用户，需要创建该用户的信息文件
     * 这些文件有：
     *         + log-1.dat 日志文件，文件名为 "log-0.dat "则不使用日志。
     *         + shares-11.dat 共享开关，11分别是 共享开关和被搜索开关
     *         + message.dat 信息文件，保存收到的消息
     * @param userId
     * @return
     */
    public static boolean makeUserFiles(String userId){
        File root=Paths.get(rootsDir,userId).toFile();
        File userFile=Paths.get(usersDir,userId,"log-1.dat").toFile();//默认打开日志
        File shareFile=Paths.get(usersDir,userId,"shares-11.dat").toFile();//默认打开共享
        try {
            root.mkdirs();
            userFile.getParentFile().mkdirs();
            userFile.createNewFile();
            shareFile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
            root.delete();
            userFile.delete();
            shareFile.delete();
            return false;
        }
        return true;

    }
    
    public static void removeUserFiles(String userId) {
        Paths.get(rootsDir,userId).toFile().delete();
        Paths.get(usersDir,userId).toFile().delete();
    }
    
    public static boolean mkdir(String idPath){
        return getRootFile(idPath).mkdirs();
    }
    public static boolean deleteFile(String idPath){
        return getRootFile(idPath).delete();
    }
    public static boolean deleteFile(File file){
        if (file==null||!file.exists()) return false;
        if (file.isFile()) return file.delete();
        if (file.isDirectory()) return deleteDir(file);
        return false;
    }
    public static boolean deleteDir(File file){
        if (file==null||!file.exists()) return false;
        if (!file.delete()){
            for (File f: Objects.requireNonNull(file.listFiles()))
                if (!file.delete())
                    if (!deleteDir(f)) return false;
            return file.delete();
        }
        return !file.exists();
    }
    public static boolean moveFile(String sourceIdPath,String distIdPath){
        return getRootFile(sourceIdPath).renameTo(getRootFile(distIdPath));
    }
    private static File getRootFile(String idPath){
        return Paths.get(rootsDir,idPath).toFile();
    }
    /**
     *
     * @param anon 是否匿名
     * @param read 读还是写
     * @param userId 目标 id
     * @param path 目录
     * @return: 成功与否
     * @author: 本小蛋
     * @time: 2021/9/6 21:37
     */
    public static boolean isGranted(boolean anon,boolean read,String userId,String path){
        File file = Paths.get(usersDir,userId,Share.shareOpenOpen).toFile();
        if (!file.isFile()) file = Paths.get(usersDir,userId,Share.shareOpenClose).toFile();
        if (!file.isFile()) return false;
        try (BufferedReader br = new BufferedReader(new FileReader(file))) {
            String line=null;
            while ((line=br.readLine())!=null){
                if (line.startsWith(path)){//startWith() 保证子文件夹也能访问
                   String pem= line.split(" ")[2];
                   if (anon){//匿名访问
                       //01-34-67
                       if (read) return pem.charAt(0)=='1';//匿名读
                       else return pem.charAt(1)=='1';//匿名写
                   }else {//用户访问
                       //匿名权限开了的话就不用判断用户权限了
                       if (read) return pem.charAt(0) == '1' || pem.charAt(3) == '1';
                       else return pem.charAt(1) == '1' || pem.charAt(4)=='1';
                   }
                }
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    public static boolean isSearchedOpen(String userId){
        if (Paths.get(usersDir,userId,Share.shareOpenOpen).toFile().exists())return true;
        if (Paths.get(usersDir,userId,Share.shareCloseOpen).toFile().exists())return true;
        return false;
    }
    public static boolean isShareOpen(String userId){
        if (Paths.get(usersDir,userId,Share.shareOpenOpen).toFile().exists())return true;
        if (Paths.get(usersDir,userId,Share.shareOpenClose).toFile().exists())return true;
        return false;
    }
    /**
     * 已弃用，使用数据库了
     * 添加共享文件夹，不做合法判断
     * @param share Share
     * @return:
     * @author: 本小蛋
     * @time: 2021/9/6 22:47
     */
    @Deprecated
    public static boolean addShare(Share share) {
        File file = new File(usersDir+"/"+share.userId+"/");
        for (File f:file.listFiles()){//找 share-xx
            if (f.getName().startsWith("share")){
                file=f;
                break;
            }
        }
        return appendLineToFile(share.toString(),file);
    }

    /**
     * 在文件后添加字符串
     * @param str 要添加的字符
     * @param file 文件
     * @return 成功与否
     */
    public static boolean appendLineToFile(String str,File file){
        try (BufferedWriter bw = new BufferedWriter(new FileWriter(file,true))) {
            bw.write(str+"\n");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     *  根据userId获取其share list的读取流
     * @param userId 用户id
     * @return: BufferedReader
     * @author: 本小蛋
     * @time: 2021/9/8 9:49
     */
    public static BufferedReader getShareFilesBufReader(String userId){
        File file= Paths.get(usersDir,Share.shareOpenOpen).toFile();
        if (!file.exists())file=Paths.get(usersDir,Share.shareOpenClose).toFile();
        if (!file.exists())return null;
        try {
            return new BufferedReader(new FileReader(file));
        } catch (FileNotFoundException e) {
            return null;
        }
    }
    public static BufferedWriter getShareFilesBufWriter(String userId){
        File file= Paths.get(usersDir,Share.shareOpenOpen).toFile();
        if (!file.exists())file=Paths.get(usersDir,Share.shareOpenClose).toFile();
        if (!file.exists())return null;
        try {
            return new BufferedWriter(new FileWriter(file));
        } catch (Exception e) {
            return null;
        }
    }
    public static boolean writeInputStreamToFile(InputStream is,File distFile){
        System.out.println("写到："+distFile.getAbsolutePath());
        try {
            OutputStream os = new FileOutputStream(distFile);
            byte[] bytes=new byte[1024];
            int length = 0;
            while ((length=is.read(bytes))!=-1)
                os.write(bytes,0,length);
            is.close();
            os.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 合并文件，合并完成不会自动删除原文件
     * @param sourceFiles 分片文件
     * @param targetFile 目的文件
     */
    public static boolean mergeFiles(File[] sourceFiles, File targetFile) {
        System.out.println("合并到："+targetFile.getAbsolutePath());
        if (sourceFiles == null || sourceFiles.length < 1 || targetFile.exists()) {
            return false;
        }
        if (sourceFiles.length == 1) {
            return sourceFiles[0].renameTo(targetFile);
        }

        try {
            FileChannel resultFileChannel = new FileOutputStream(targetFile, true).getChannel();
            for (File file:sourceFiles) {
                FileChannel blk = new FileInputStream(file).getChannel();
                resultFileChannel.transferFrom(blk, resultFileChannel.size(), blk.size());
                blk.close();
            }
            resultFileChannel.close();
        } catch (IOException e) {
            targetFile.delete();
            e.printStackTrace();
            return false;
        }
        return true;
    }
}
